/**yield关键字
 * 让生成器开始或者恢复
 * 
 * 生成器之间不影响
 * 
 */

function* generatorFn(){
    yield 'foo';
    yield 'bar';
    return 'baz';
}

let generatorObj = generatorFn()
console.log(generatorObj.next());
console.log(generatorObj.next());
console.log(generatorObj.next());
//{ value: 'foo', done: false }
//{ value: 'bar', done: false }
//{ value: 'baz', done: true }


//生成器之间不影响
let generatorObj1 = generatorFn()
let generatorObj2 = generatorFn()


console.log(generatorObj1.next());
console.log(generatorObj2.next());
//{ value: 'foo', done: false }
//{ value: 'foo', done: false }


//只能生成器函数内部使用，在嵌套的函数中使用无效

//有效
function* validGeneratorFn(){
    yield 'foo';
}
validGeneratorFn()

//无效
// function* validGeneratorFnA(){
//     ()=>{
//         yield 'foo';
//     }
// }
// validGeneratorFnA()

//报错


/***
 * 1.生成器对象作为可迭代对象
 */
 function* intGeneratorFn(){
    yield 1;
    yield 2;
    yield 3;
}

for (const i of intGeneratorFn()) {
    console.log(i);
}
//1
//2
//3

//生成整数
function* setRange(n){
    while (n--) {
        yield n
    }
}

for (const i of setRange(5)) {
    console.log(i);
}
//4
//3
//2
//1
//0


/**
 * 2.使用yield实现输入输出
 */

//第一次调用next（）方法，传的值不会使用
function* runGeneratorFn(ini) {
    console.log(ini);
    console.log(yield);
    console.log(yield);
}

generatorObj = runGeneratorFn('foo')
generatorObj.next('bar');//传的值不会使用
generatorObj.next('baz');
generatorObj.next('qux');
//foo
//baz
//qux

//yield同时用于输入输出

function* runGeneratorFn2() {
    return yield 'foo';
}

generatorObj = runGeneratorFn2()
console.log(generatorObj.next());
console.log(generatorObj.next('bar'));
//{ value: 'foo', done: false }
//{ value: 'bar', done: true }

///实现范围数组
function* range(start,end) {
    while (end>start) {
        yield start++
    }
}

for (const i of range(5,10)) {
    console.log(i);
}
//5
//6
//7
//8
//9

//填充数组
function* zeroes(n){
    while (n--) {
        yield '0';
    }
}

console.log(Array.from(zeroes(5)));
//[ '0', '0', '0', '0', '0' ]


/**
 * 3.产生可迭代对象
 */
function* generatorFn6(){
    for (const i of [1,2,3]) {
        yield i;
    }
}

//等价的方法(更简洁)
function* generatorFn7(){
    yield* [1,2,3];
}


for (const i of generatorFn7()) {
    console.log(i);
}
//1
//2
//3


//yield*实际是产生一串单独的值
function* generatorFn8(){
    yield* [1,2,3];
    yield* [4,5,6];
    yield* [10,11,12];
}
for (const i of generatorFn8()) {
    console.log(i);
}
//1
//2
//3
//4
//5
//6
//10
//11
//12

//yield*的值

//1.普通迭代对象，yield*的值是value
function* generatorFn9(){
    console.log('迭代器值：',yield* [1,2,3]);
}

for (const i of generatorFn9()) {
    console.log('遍历的值：',i);
}
//遍历的值： 1
//遍历的值： 2
//遍历的值： 3
//迭代器值： undefined


//2.对于生成器函数,yield*的值是return后的值
function* initGeneratorFn(){
    yield 'foo';
    return 'bar'
}

function* outGeneratorFn(){
    console.log('迭代器值：',yield* initGeneratorFn());
}

for (const i of outGeneratorFn()) {
    console.log('遍历的值：',i);
}



/**
 * 4.使用yield*实现递归算法
 * 
 */

function* nTimes(n){
    if (n>0) {
        yield* nTimes(n-1)
        yield n-1
    }
}

for (const i of nTimes(3)) {
    console.log(i);
}
//0
//1
//2


/**
 * 双向连接
 */
class Node {
    constructor(id){
        this.id = id;
        this.neighbors = new Set();
    }

    connect(node){
        if(node !== this){
            this.neighbors.add(node);
            node.neighbors.add(this)
        }
    }
}

/**
 * 随机生成
 */
class RandomGraph{
    constructor(size){
        this.nodes = new Set();
        //创建节点
        for (let i = 0; i < size; i++) {
            this.nodes.add(new Node(i))
        }
        //随机连接节点
        const threshold = 1 / size;
        for (const x of this.nodes) {
            for (const y of this.nodes) {
                if (Math.random() < threshold) {
                    x.connect(y)
                }
            }
        }
    }
    /**
     * 打印
     */
    print(){
        for (const node of this.nodes) {
            const ids = [...node.neighbors].map((n)=>n.id).join(',')
            console.log(`${node.id}: ${ids}`);
        }
    }

    isConneced(){
        const visitedNodes = new Set();
        
        function* traverse(nodes){
            for (const node of nodes) {
                if(!visitedNodes.has(node)){
                    yield node;
                    yield* traverse(node.neighbors)
                }
            }
        }
        //取得集合中的第一个节点
        const firstNode = this.nodes[Symbol.iterator] ().next().value;
        console.log([firstNode]);
        for (const node of traverse([firstNode])) {
            visitedNodes.add(node)
        }
        console.log('显示的个数',visitedNodes.size );
        console.log('总个数',this.nodes.size);
        return visitedNodes.size === this.nodes.size;
    }
}

const g = new RandomGraph(6);
g.print();
console.log(g.isConneced());

//0: 1
//1: 0,3,4
//2: 3,4
//3: 2,1
//4: 2,1,5
//5: 4

